﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

// 2008 by Mario Meir-Huber
// Mail: mario_mh@vb-magazin.de
//       i-mameir@microsoft.com
namespace ChartLibrary.Data
{
    /// <summary>
    /// This is the main Data Object where the chart stores its data
    /// </summary>
    /// <history>
    ///     03/15/08: Design and Implementation for 0.1
    /// </history>
    public class DataModel : IDataChanged, IEnumerator<DataSource>, IEnumerable<DataSource>
    {
        private List<DataSource> _lst = null;       //this stores the data
        private double _min = 0.0;                  //the minimal value over all data sources
        private double _max = 0.0;                  //the maximal value over all data sources
        private object _tag = null;                 //tag to store custom data
        private int _enumpositon = -1;              //enumerator position

        public event ChartLibrary.Base.DataChangedEvent DataChanged; //delegate to changed data

        /// <summary>
        /// Initializes the Data Model
        /// </summary>
        public DataModel()
        {
            _lst = new List<DataSource>();
        }

        /// <summary>
        /// This is handled from the Child to Notify the Parent that data was changed
        /// </summary>
        /// <param name="sender"></param>
        public void NotifyDataChanged(object sender)
        {
            UpdateMinMax();

            if (null != DataChanged) DataChanged();
        }

        /// <summary>
        /// This updates the lowest and highest value
        /// </summary>
        /// <history>
        ///    03/18/08: Changed some logic
        /// </history>
        private void UpdateMinMax()
        {
            bool minset = false, maxset = false;
            if (_lst.Count < 1) return;

            for (int i = 0; i < _lst.Count; i++)
            {
                if (_lst[i].Length > 0)
                {
                    if (!minset)
                    {
                        _min = _lst[i].Min;
                        minset = true;
                    }

                    if (!maxset)
                    {
                        _max = _lst[i].Max;
                        maxset = true;
                    }

                    if (_lst[i].Max > _max) _max = _lst[i].Max;
                    if (_lst[i].Min < _min) _min = _lst[i].Min;
                }
            }
        }

        /// <summary>
        /// Adds a new Datasource to the Collection
        /// </summary>
        /// <returns>New Datasource Object</returns>
        public DataSource Add()
        {
            return Add("Unnamed Datasource");
        }

        /// <summary>
        /// Adds a new Datasource to the Collection
        /// </summary>
        /// <param name="name">Name of the object</param>
        /// <returns></returns>
        public DataSource Add(String name)
        {
            DataSource ds = new DataSource(this, name);
            return Add(ds);
        }

        /// <summary>
        /// Adds a new Datasource to the Collection
        /// </summary>
        /// <param name="data">Datasource Item</param>
        /// <returns></returns>
        public DataSource Add(DataSource data)
        {
            _lst.Add(data);
            return data;
        }

        /// <summary>
        /// Clears the list
        /// </summary>
        public void Clear()
        {
            _lst.Clear();
        }

        /// <summary>
        /// Removes an Item
        /// </summary>
        /// <param name="item"></param>
        public void Remove(DataSource item)
        {
            _lst.Remove(item);
        }

        /// <summary>
        /// Removes an item at the index
        /// </summary>
        /// <param name="index">Position</param>
        public void RemoveAt(int index)
        {
            _lst.RemoveAt(index);
        }

        /// <summary>
        /// Gets a Tag for the Class or sets it
        /// </summary>
        public object Tag
        {
            get { return _tag; }
            set { _tag = value; }
        }

        /// <summary>
        /// Gets the minimal value 
        /// </summary>
        public double Min
        {
            get { return _min; }
        }

        /// <summary>
        /// Gets the maximum value
        /// </summary>
        public double Max
        {
            get { return _max; }
        }

        /// <summary>
        /// This returns the count of the Data Sources
        /// </summary>
        public int Count
        {
            get { return _lst.Count; }
        }

        /// <summary>
        /// Gets the Datasource at the specified position or sets it
        /// </summary>
        /// <param name="i">Index</param>
        /// <returns></returns>
        public DataSource this[int i]
        {
            get
            {
                if (i >= _lst.Count) throw new IndexOutOfRangeException("The index is out of the bounds of the array");

                return _lst[i];
            }
            set
            {
                if (i >= _lst.Count) throw new IndexOutOfRangeException("The index is out of the bounds of the array");

                _lst[i] = value;
            }
        }

        #region IEnumerator<DataSource> Members

        public DataSource Current
        {
            get { return _lst[_enumpositon]; }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            _enumpositon = -1;
        }

        #endregion

        #region IEnumerator Members

        object System.Collections.IEnumerator.Current
        {
            get { return _lst[_enumpositon]; }
        }

        public bool MoveNext()
        {
            _enumpositon++;

            if (_enumpositon < _lst.Count) return true;
            else return false;
        }

        public void Reset()
        {
            _enumpositon = -1;
        }

        #endregion

        #region IEnumerable<DataSource> Members

        public IEnumerator<DataSource> GetEnumerator()
        {
            return this;
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this;
        }

        #endregion
    }
}
